package com.fengquan.slicing.application.Impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.fengquan.slicing.application.IFileApplication;
import com.fengquan.slicing.dto.XmlData;
import com.fengquan.slicing.entity.Md5File;
import com.fengquan.slicing.entity.Md5List;
import com.fengquan.slicing.service.IMd5FileService;
import com.fengquan.slicing.service.IMd5ListService;
import com.fengquan.slicing.service.IMd5RecordService;
import com.fengquan.slicing.util.UUIDUtil;
import com.mongodb.client.gridfs.GridFSBucket;
import com.mongodb.client.gridfs.GridFSDownloadStream;
import com.mongodb.client.gridfs.model.GridFSFile;
import lombok.extern.slf4j.Slf4j;
import org.apache.tomcat.util.http.fileupload.IOUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.mongodb.core.query.Criteria;
import org.springframework.data.mongodb.core.query.Query;
import org.springframework.data.mongodb.gridfs.GridFsResource;
import org.springframework.data.mongodb.gridfs.GridFsTemplate;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/************************************************************
 * 作    者: P622311(冯泉)
 * 日    期: 2021/3/18 12:07
 * 用途说明: (分片下载实现类)
 ************************************************************/
@Component
@Slf4j
public class FileApplicationImpl implements IFileApplication {

    @Autowired
    private IMd5FileService fileService;

    @Autowired
    private IMd5ListService listService;

    @Autowired
    private IMd5RecordService recordService;

    @Autowired
    private GridFsTemplate gridFsTemplate;

    @Autowired
    private GridFSBucket gridFSBucket;

    /**
     * 分片上传
     * @param data
    @Autowired
     * @return
     * @throws Exception
     */
    @Override
    public synchronized Map update(XmlData data, MultipartFile file) throws Exception{
        Map map=new HashMap<String,Object>();
        map.put("index",-1);
        //saveFile(file);//保存附件到服务器
        Md5List md5List=new Md5List();
        md5List.setId(UUIDUtil.randomUUID());
        md5List.setMd5Id(data.getId());
        //Blob blob=new SerialBlob(file.getBytes());

        //存储文件到mongo
        // 获得提交的文件名
        String fileName = file.getOriginalFilename();
        // 获取文件输入流
        InputStream ins = file.getInputStream();
        // 获取文件类型
        String contentType = file.getContentType();
        md5List.setFileid(gridFsTemplate.store(ins, fileName, contentType).toString());

        //存储文件到mysql
        //md5List.setContent(file.getBytes());

        md5List.setFilename(data.getFileName());
        md5List.setInd(data.getIndex());
        md5List.setMd5(data.getMd5());
        md5List.setState(1);
        checkMd5List(md5List,data.getList());

        QueryWrapper<Md5File> fileQueryWrapper=new QueryWrapper<>();
        fileQueryWrapper.eq("md5",md5List.getMd5Id());
        Md5File obj=fileService.getOne(fileQueryWrapper);

        QueryWrapper<Md5List> listQueryWrapper=new QueryWrapper<>();
        listQueryWrapper.eq("md5",md5List.getMd5());
        listQueryWrapper.eq("state",1);
        if(listService.count(listQueryWrapper)==0){
            listService.save(md5List);
            map.put("index",0);
            Md5File md5File=new Md5File();
            md5File.setId(UUIDUtil.randomUUID());
            md5File.setMd5(data.getId());
            md5File.setFileName(data.getFileName());
            md5File.setInd(data.getIndex());
            md5File.setLen(data.getLength());
            md5File.setState(1);
            String temp="";
            if(data.getList().size()>0){
                for(String sb:data.getList()){
                    temp+=sb+",";
                }
                temp=temp.substring(0,temp.length()-1);
                md5File.setData(temp);
            }
            if(checkMd5File(md5File)>0){
                fileService.save(md5File);
            }
        }

        if(obj!=null){
            if(listService.count(listQueryWrapper)<obj.getLen()){
                map.put("index",0);
            }
        }

        QueryWrapper<Md5List> queryWrapper=new QueryWrapper<>();
        queryWrapper.notIn("md5_id",data.getMd5());
        List<Md5List> list=listService.list(queryWrapper);
        List<String> temp1=new ArrayList<>();
        for(Md5List t:list){
            temp1.add(t.getMd5());
        }
        List<String> temp2=data.getList();
        temp2.removeAll(temp1);
        map.put("list",temp2);
        return map;
    }

    /**
     * 合流
     * @param md5
     */
    @Override
    public synchronized void confluence(String md5)throws Exception{
        QueryWrapper<Md5List> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("md5_id",md5);
        queryWrapper.orderByAsc("ind");
        List<Md5List> list=listService.list(queryWrapper);
        String path = System.getProperty("user.dir")+"\\Logs\\"+ list.get(0).getFilename();
        File file = new File(path);
        FileOutputStream fos = new FileOutputStream(file);
        for(Md5List sd:list){
            byte[] bytes=sd.getContent();
            fos.write(bytes, 0, bytes.length);
        }
        fos.flush();
        fos.close();
    }

    /**
     * 分片下载
     * @param md5
     * @param request
     * @param response
     * @throws Exception
     */
    @Override
    public void download3(String md5, HttpServletRequest request, HttpServletResponse response) throws Exception {
        QueryWrapper<Md5List> listQueryWrapper=new QueryWrapper<>();
        listQueryWrapper.eq("md5",md5);
        Md5List file=listService.getOne(listQueryWrapper);

        Query query = Query.query(Criteria.where("_id").is(file.getFileid()));
        // 查询单个文件
        GridFSFile gridFSFile = gridFsTemplate.findOne(query);
        if (gridFSFile == null) {
            return;
        }

        GridFSDownloadStream gridFSDownloadStream = gridFSBucket.openDownloadStream(gridFSFile.getObjectId());
        GridFsResource resource = new GridFsResource(gridFSFile, gridFSDownloadStream);

        OutputStream outputStream = response.getOutputStream();
        InputStream inputStream = resource.getInputStream();
        IOUtils.copy(inputStream, outputStream);
        outputStream.flush();
        outputStream.close();
        inputStream.close();
    }

    /**
     * 文件信息
     * @param md5
     * @return
     */
    @Override
    public List fileInfo(String md5) {
        QueryWrapper<Md5List> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("md5_id",md5);
        queryWrapper.orderByAsc("ind");
        List<Md5List> list=listService.list(queryWrapper);
        for(Md5List entity:list){
            entity.setContent(null);
        }
        List<Md5List> temp=new ArrayList<>();
        for (int i=0;i<list.size();i++){
            if(i%2==0){
                temp.add(list.get(i));
            }
        }
        for (int i=0;i<list.size();i++){
            if(i%2!=0){
                temp.add(list.get(i));
            }
        }
        return temp;
    }

    /**
     * 校验md5是否保存
     * @param md5
     * @return
     * @throws Exception
     */
    int checkMd5File(Md5File md5) throws Exception{
        QueryWrapper<Md5File> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("md5",md5.getMd5());
        queryWrapper.eq("state",1);
        if(fileService.count(queryWrapper)>0){
            return -1;
        }
        return 1;
    }

    /**
     * 校验块  是否重复上传
     * @param md5
     * @throws Exception
     */
    void checkMd5List(Md5List md5,List list) throws Exception{
        QueryWrapper<Md5List> queryWrapper=new QueryWrapper<>();
        queryWrapper.eq("md5_id",md5.getMd5Id());
        queryWrapper.eq("state",1);
        if(listService.count(queryWrapper)==list.size()){
            throw new Exception("该文件已上传");
        }
    }

}
